﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Connection;
using System.Data;
using NHibernate.Mapping.ByCode;
using Nhibernate.GuitarStore.Common;
using NHibernate.Cfg.MappingSchema;

namespace Nhibernate.GuitarStore.DataAccess
{
    public class NHibernateBase
    {
        private static NHibernate.Cfg.Configuration Configuration { get; set; }
        protected static ISessionFactory SessionFactory { get; set; }
        private static ISession session = null;
        private static IStatelessSession statelessSession = null;

        public static NHibernate.Cfg.Configuration ConfigureNHibernate(string assembly)
        {
            Configuration = new NHibernate.Cfg.Configuration();

            Configuration.DataBaseIntegration(dbi =>
            {
                dbi.Dialect<MsSql2008Dialect>();
                dbi.Driver<SqlClientDriver>();
                dbi.ConnectionStringName = "GuitarStore";
                dbi.ConnectionProvider<DriverConnectionProvider>();                
                dbi.IsolationLevel = IsolationLevel.ReadUncommitted;
                dbi.Timeout = 15;
                dbi.BatchSize = 10;
            });

            //Configuration.Cache(ca =>
            //{
            //    ca.Provider<NHibernate.Cache.HashtableCacheProvider>();
            //});

            //Configuration.Proxy(pxy =>
            //{
            //    pxy.Validation = false;
            //    pxy.ProxyFactoryFactory<DefaultProxyFactory>();
            //});

            /******************************************************/
            //turtorial mapping
            
            var modelMapper = new ModelMapper();
           Type[] mappingTypes = typeof (InventoryMap).Assembly.GetExportedTypes()
               .Where(t => t.Name.EndsWith("Map")).ToArray();
           modelMapper.AddMappings(mappingTypes);
           //var configuration = new Configuration();
           Configuration.AddMapping(modelMapper
                                     .CompileMappingForAllExplicitlyAddedEntities());  
            
            /******************************************************/
            /* original code
            ModelMapper mapper = new ModelMapper();
            //mapper.AddMappings(typeof(AnyMappingClass).Assembly.GetTypes());
            //mapper.AddMapping(typeof(InventoryMap).Assembly.GetType());
            
            mapper.AddMapping<InventoryMap>();
            HbmMapping mapping = mapper.CompileMappingFor(new[] { typeof(Inventory) });
            Configuration.AddDeserializedMapping(mapping, null);
            */
            //Todo: lenh nay cam giac khong can
            //Configuration.AddAssembly(assembly);

            return Configuration;
        }
        
        public void Initialize(string assembly)
        {
            Configuration = ConfigureNHibernate(assembly);
            SessionFactory = Configuration.BuildSessionFactory();
        }

        public static ISession Session
        {
            get
            {
                if (session == null)
                {
                    session = SessionFactory.OpenSession();
                }

                return session;
            }
        }

        public static IStatelessSession StatelessSession
        {
            get
            {
                if (statelessSession == null)
                {
                    statelessSession = SessionFactory.OpenStatelessSession();
                }

                return statelessSession;
            }
        }

        public IList<T> ExecuteICriteria<T>()
        {
            using (ITransaction transaction = Session.BeginTransaction())
            {
                try
                {
                    IList<T> result = Session.CreateCriteria(typeof(T)).List<T>();
                    transaction.Commit();
                    return result;
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }
    }
}
